package org.eclipse.epsilon.emc.jdt;

import org.eclipse.epsilon.emc.jdt.properties.CompilationUnitProperties;
import org.eclipse.epsilon.emc.jdt.properties.EnumDecProperties;
import org.eclipse.epsilon.emc.jdt.properties.JavaProjectProperties;
import org.eclipse.epsilon.emc.jdt.properties.PackageProperties;
import org.eclipse.epsilon.emc.jdt.properties.SingleVariableDecProperties;
import org.eclipse.epsilon.emc.jdt.properties.Properties;
import org.eclipse.epsilon.emc.jdt.properties.TypeDecProperties;
import org.eclipse.epsilon.emc.jdt.properties.VariableDecFragProperties;
import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
import org.eclipse.epsilon.eol.execute.introspection.java.JavaPropertyGetter;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;

/**
 * This class retrieves the value of properties of JDT model element
 * 
 * @author Cheng Yun
 * 
 */
public class JdtPropertyGetter extends JavaPropertyGetter {
	@Override
	public Object invoke(Object object, String property)
			throws EolRuntimeException {
		try {
			if (object instanceof IJavaProject) {// JavaProjact

				return JavaProjectProperties.getProperty(property).run(object);
			}

			if (object instanceof IPackageFragment) {// Package
				return PackageProperties.getProperty(property).run(object);
			}
			
			if (object instanceof ASTNode) {//ASTNode
				ASTNode node = (ASTNode) object;
				if (property.equals("type")) {// ASTNode.type
					return ASTNode.nodeClassForType(node.getNodeType());
				}
			}
			
			if (object instanceof CompilationUnit){// JavaFile
				return CompilationUnitProperties.getProperty(property).run(object);
			}

			if (object instanceof TypeDeclaration) {// Class
				return TypeDecProperties.getProperty(property).run(object);
			}
			
			if (object instanceof EnumDeclaration) {// Enumeration
				return EnumDecProperties.getProperty(property).run(object);
			}

			if (object instanceof FieldDeclaration) {// Field
				FieldDeclaration field = (FieldDeclaration) object;
				return Properties.getProperty(property).run(field);
			}

			if (object instanceof MethodDeclaration) {// Method
				MethodDeclaration method = (MethodDeclaration) object;
				return Properties.getProperty(property).run(method);
			}
			
			if (object instanceof VariableDeclaration){// VariableDeclaration
				if (object instanceof SingleVariableDeclaration) {
					return SingleVariableDecProperties.getProperty(property).run(object);
				}
				
				if (object instanceof VariableDeclarationFragment) {
					return VariableDecFragProperties.getProperty(property).run(object);
				}
			}
			//Statement or Expression
			if ((object instanceof Statement) || (object instanceof Expression)) {
				ASTNode node = (ASTNode) object;
				return Properties.getProperty(property).run(node);
			}
		} catch (NullPointerException e) {
			return super.invoke(object, property);
		}
		return super.invoke(object, property);		
	}
}
